﻿//-----------------------------------------------------------------------
// <copyright file="PivotMakerForm.cs" company="Forebrain Technology, LLC">
//
// Copyright (c) Forebrain Technology, LLC. All rights reserved.
// 
// This source code is released under the Microsoft Public License (Ms-PL).
//
// </copyright>
//-----------------------------------------------------------------------
namespace PivotCollectionMaker.WinFormApplication
{
    using System;
    using System.Drawing;
    using System.Linq;
    using System.Windows.Forms;
    using Kent.Boogaart.KBCsv;
    using PivotCollectionMaker.WinFormApplication.Controls;
    using PivotCollectionMaker.WinFormApplication.Model;
    using PivotCollectionTools.Data;
    using PivotCollectionTools.Library;
    using PivotCollectionTools.Xml;
    using System.IO;

    /// <summary>
    /// The main form for the application.
    /// </summary>
    public partial class PivotMakerForm : Form
    {
        /// <summary>
        /// Storage for the selected column.
        /// </summary>
        private DataGridViewColumn selectedColumn;

        /// <summary>
        /// Storage for the curret Pivot Collection Maker project.
        /// </summary>
        private PivotCollectionProject project;

        /// <summary>
        /// The working folder of the current project;
        /// </summary>
        private string workingFolder;

        /// <summary>
        /// Initializes a new instance of the <see cref="PivotMakerForm"/> class.
        /// </summary>
        public PivotMakerForm()
        {
            InitializeComponent();
            this.uxMainDataGrid.ColumnHeadersBorderStyle = ProperColumnHeadersBorderStyle;
        }

        /// <summary>
        /// Gets the proper column headers border style.
        /// </summary>
        /// <value>The proper column headers border style of the pivot maker form.</value>
        public static DataGridViewHeaderBorderStyle ProperColumnHeadersBorderStyle
        {
            get
            {
                return (SystemFonts.MessageBoxFont.Name == "Segoe UI") ?
                    DataGridViewHeaderBorderStyle.None :
                    DataGridViewHeaderBorderStyle.Raised;
            }
        }

        /// <summary>
        /// Binds the data.
        /// </summary>
        private void BindData()
        {
            this.uxMainDataGrid.Rows.Clear();
            this.uxMainDataGrid.Columns.Clear();

            foreach (var item in this.project.Table.Columns)
            {
                var categoryColumn = new DataGridViewTextBoxColumn() { Name = item.Name, HeaderText = item.Name };
                categoryColumn.SortMode = DataGridViewColumnSortMode.NotSortable;
                int index = this.uxMainDataGrid.Columns.Add(categoryColumn);
            }

            foreach (var dataRow in this.project.Table.DataRows)
            {
                int rowCounter = this.uxMainDataGrid.Rows.Add(dataRow.Items.ToArray());
            }

            this.uxMainDataGrid.CellValueChanged += new DataGridViewCellEventHandler(this.MainDataGrid_CellValueChanged);
            this.bindingSource1.SuspendBinding();
            this.bindingSource1.DataSource = this.project;
            this.bindingSource1.ResumeBinding();

            this.uxCategoryListView.SetViewModel(this.project.Table);   
        }

        /// <summary>
        /// Handles the CellValueChanged event of the MainDataGrid control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.DataGridViewCellEventArgs"/> instance containing the event data.</param>
        private void MainDataGrid_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex == -1 || e.RowIndex > this.project.Table.DataRows.Count)
            {
                return;
            }

            var column = uxMainDataGrid.Columns[e.ColumnIndex];

            object rowValue = uxMainDataGrid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
            if (rowValue != null)
            {
                this.project.Table.DataRows[e.RowIndex].Cells[column.DisplayIndex].Value =
                    rowValue.ToString();
            }
        }

        /// <summary>
        /// Handles the Load event of the MainForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void MainForm_Load(object sender, EventArgs e)
        {
            this.project = new PivotCollectionProject();

            this.workingFolder = Application.LocalUserAppDataPath;
            
            this.BindData();
        }

        /// <summary>
        /// Handles the MouseUp event of the MainDataGrid control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        private void MainDataGrid_MouseUp(object sender, MouseEventArgs e)
        {
            // Load context menu on right mouse click
            DataGridView.HitTestInfo hitTestInfo;

            hitTestInfo = this.uxMainDataGrid.HitTest(e.X, e.Y);
            if (hitTestInfo.ColumnIndex < 0)
            {
                return;
            }

            this.selectedColumn = this.uxMainDataGrid.Columns[hitTestInfo.ColumnIndex];
            this.ColumnChanged();
        }

        /// <summary>
        /// Columns the changed.
        /// </summary>
        private void ColumnChanged()
        {
            if (string.IsNullOrEmpty(this.selectedColumn.Name))
            {
                return;
            }

            PivotTableCategory category = this.project.Table.Columns[this.selectedColumn.Name].Category;
        }

        /// <summary>
        /// Handles the CellValidating event of the MainDataGrid control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.DataGridViewCellValidatingEventArgs"/> instance containing the event data.</param>
        private void MainDataGrid_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            if (e.RowIndex == -1 || this.project.Table.DataRows.Count <= 0 || e.RowIndex > this.project.Table.DataRows.Count - 1)
            {
                return;
            }

            var column = uxMainDataGrid.Columns[e.ColumnIndex];
            
            string x = this.project.Table.DataRows[e.RowIndex].Cells[column.DisplayIndex].Value;
            
            if (uxMainDataGrid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value != null)
            {
                string z = uxMainDataGrid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
            }
        }

        /// <summary>
        /// Handles the UserAddedRow event of the MainDataGrid control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.DataGridViewRowEventArgs"/> instance containing the event data.</param>
        private void MainDataGrid_UserAddedRow(object sender, DataGridViewRowEventArgs e)
        {
            this.project.Table.NewRow();
        }

        /// <summary>
        /// Handles the Click event of the NewToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void NewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.uxCategoryListView.Clear();
            this.project.Clear();
            this.BindData();
        }

        /// <summary>
        /// Handles the Click event of the OpenToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void OpenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.uxOpenProjectFileDialog.ShowDialog() == DialogResult.OK)
            {
                this.workingFolder = Path.GetDirectoryName(this.uxOpenProjectFileDialog.FileName);
                this.project = PivotCollectionProject.LoadProject(this.uxOpenProjectFileDialog.FileName);
                this.BindData();
            }
        }

        /// <summary>
        /// Handles the Click event of the SaveAsToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void SaveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.uxSaveProjectFileDialog.ShowDialog() == DialogResult.OK)
            {
                this.project.SaveProject(this.uxSaveProjectFileDialog.FileName);
            }
        }

        /// <summary>
        /// Handles the Click event of the PublishToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void PublishToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string publishFolder = IsPathRooted(this.project.PublishFolder) ?
                this.project.PublishFolder : Path.Combine(this.workingFolder, this.project.PublishFolder);

            string projectFileName = Path.HasExtension(this.project.CollectionTitle) ?
                this.project.CollectionTitle : string.Concat(this.project.CollectionTitle, ".cxml");

            var creator = new PivotCollectionBuilder(this.project.Table);
            using (new CursorKeeper(Cursors.WaitCursor))
            {
                creator.CreateCollection(
                    publishFolder,
                    this.project.ConvertedImageFolder,
                    this.project.DeepZoomCollectionName,
                    this.project.PivotCollectionFileName,
                    projectFileName);
            }

            MessageBox.Show("Pivot Collection buildig complete.", "Done.", MessageBoxButtons.OK);
        }

        /// <summary>
        /// Handles the Click event of the AddColumnToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void AddColumnToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var addForm = new AddColumnForm()
            {
                Model = new TableSchemaModel()
                {
                    Table = this.project.Table
                }
            };

            if (addForm.ShowDialog() == DialogResult.OK)
            {
                var newColumn = new DataGridViewTextBoxColumn() 
                { 
                    Name = addForm.Model.NewColumn.Name,
                    HeaderText = addForm.Model.NewColumn.Name
                };
                newColumn.SortMode = DataGridViewColumnSortMode.NotSortable;
                this.uxMainDataGrid.Columns.Add(newColumn);
            }
        }

        /// <summary>
        /// Handles the Click event of the AddCategoryToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void AddCategoryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var addForm = new PivotTableCategoryForm()
            {
                Model = new PivotTableCategory("New Category", PivotTableCellType.Text)
            };
            if (addForm.ShowDialog() == DialogResult.OK)
            {
                this.project.Table.Categories.Add(addForm.Model);
            }
        }

        /// <summary>
        /// Handles the Click event of the ImportXmlToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void ImportXmlToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.uxImportPivotXmlDialog.ShowDialog() == DialogResult.OK)
            {
                var builder = new PivotTableBuilder();
                this.project.Clear();

                builder.ReadFromXml(this.project.Table, this.uxImportPivotXmlDialog.FileName);
                this.project.CollectionTitle = builder.LastXmlRead.Name;
                this.project.DeepZoomCollectionName = builder.LastXmlRead.ItemList[0].ImageBase;
                this.BindData();
            }
        }

        /// <summary>
        /// Handles the Click event of the SaveCXMLToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void SaveCXMLToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.uxSavePivotXmlDialog.ShowDialog() == DialogResult.OK)
            {
                var builder = new PivotXmlBuilder()
                {
                    CollectionTitle = this.project.CollectionTitle,
                    ImageBase = this.project.DeepZoomCollectionName
                };

                PivotXml xml = builder.CreatePivotXml(this.project.Table);
                xml.WriteXml(this.uxSavePivotXmlDialog.FileName);
            }
        }

        /// <summary>
        /// Handles the BeforeCategoryDeleted event of the CategoryListView control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="PivotCollectionMaker.WinFormApplication.Controls.CategoryListViewEventArgs"/> instance containing the event data.</param>
        private void CategoryListView_BeforeCategoryDeleted(object sender, CategoryListViewEventArgs e)
        {
            if (MessageBox.Show("Delete Category?", "Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
            {
                e.Continue = false;
            }
        }

        /// <summary>
        /// Handles the BeforeColumnDeleted event of the CategoryListView control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="PivotCollectionMaker.WinFormApplication.Controls.ColumnListViewEventArgs"/> instance containing the event data.</param>
        private void CategoryListView_BeforeColumnDeleted(object sender, ColumnListViewEventArgs e)
        {
            string message = string.Concat("Delete Column ", e.Column.Name);
            if (MessageBox.Show(message, "Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
            {
                e.Continue = false;
            }
        }

        /// <summary>
        /// Handles the Click event of the ExportDataButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void ExportDataButton_Click(object sender, EventArgs e)
        {
            if (this.uxExportDataFileDialog.ShowDialog() == DialogResult.OK)
            {
                var cursorKeep = new CursorKeeper(Cursors.WaitCursor);
                var writer = new CsvWriter(this.uxExportDataFileDialog.FileName);

                try
                {
                    writer.WriteHeaderRecord(this.project.Table.Columns.DataBoundColumnNames.ToArray());
                    foreach (var dataRow in this.project.Table.DataRows)
                    {
                        writer.WriteDataRecord(dataRow.DataBoundItems.ToArray());
                    }
                }
                catch
                {
                    MessageBox.Show("Error exporting data.", "Error.", MessageBoxButtons.OK);
                }
                finally
                {
                    writer.Close();
                    cursorKeep.Dispose();
                }
            }
        }

        /// <summary>
        /// Handles the Click event of the ImportDataButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void ImportDataButton_Click(object sender, EventArgs e)
        {
            if (this.uxImportDataFileDialog.ShowDialog() == DialogResult.OK)
            {
                var cursorKeep = new CursorKeeper(Cursors.WaitCursor);
                var reader = new CsvReader(this.uxImportDataFileDialog.FileName);

                try
                {
                    HeaderRecord header = reader.ReadHeaderRecord();

                    foreach (var record in reader.DataRecords)
                    {
                        var newDataRow = this.project.Table.NewRow();
                        foreach (var column in this.project.Table.Columns)
                        {
                            newDataRow[column.Name].Value = record[column.Name];
                        }
                    }
                }
                catch
                {
                    MessageBox.Show("Error exporting data.", "Error.", MessageBoxButtons.OK);
                }
                finally
                {
                    reader.Close();
                    cursorKeep.Dispose();
                    this.BindData();
                }
            }
        }

        /// <summary>
        /// Handles the Click event of the ClearDataToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void ClearDataToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.project.Table.ClearData();
            this.BindData();
        }

        /// <summary>
        /// Handles the SchemaChanged event of the CategoryListView control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void CategoryListView_SchemaChanged(object sender, EventArgs e)
        {
            this.BindData();
        }
    }
}
